package com.neihe.listenner.task;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.neihe.common.enums.DelFlagEnum;
import com.neihe.entity.UserFile;
import com.neihe.entity.dto.file.DeleteFileDTO;
import com.neihe.service.IRecycleService;
import com.neihe.service.IUserFileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 清理过期用户文件任务
 */
@Slf4j
@Component
public class CleanExpireUserFileTask {

    /**
     * 滚动最大查询条数
     */
    private static final Long BATCH_SIZE = 500L;

    @Autowired
    private IUserFileService userFileService;

    @Autowired
    private IRecycleService recycleService;

    /**
     * 每天凌晨00:00执行清理任务
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void run() {
        long startTime = System.currentTimeMillis();
        log.info("开始执行文件清理任务...");
        List<UserFile> expireUserFileRecords;
        Long scrollPointer = 1L;

        do {
            expireUserFileRecords = scrollQueryExpireUserFileRecords(scrollPointer);
            if (CollUtil.isNotEmpty(expireUserFileRecords)) {
                // 满足删除条件的文件集合
                Map<Long, List<Long>> userFileIdsMap = expireUserFileRecords.stream()
                        .collect(Collectors.groupingBy(
                                UserFile::getUserId,
                                Collectors.mapping(UserFile::getFileId, Collectors.toList())
                        ));

                Long maxFileId = expireUserFileRecords.stream()
                        .map(UserFile::getFileId)
                        .max(Long::compareTo)
                        .orElse(scrollPointer); // 如果集合为空则保持原指针

                userFileIdsMap.forEach((userId, fileIds) -> {
                    DeleteFileDTO vo = new DeleteFileDTO();
                    vo.setUserId(userId);
                    vo.setFileIds(fileIds);
                    recycleService.delete(vo);
                });

                // 更新滚动指针
                scrollPointer = maxFileId;
            }

        } while (CollUtil.isNotEmpty(expireUserFileRecords));
        long endTime = System.currentTimeMillis();
        log.info("文件清理任务完成，耗时: {} 秒", (endTime - startTime) / 1000);
    }

    /**
     * 滚动查询过期用户文件记录
     *
     * @param scrollPointer 滚动指针
     */
    private List<UserFile> scrollQueryExpireUserFileRecords(Long scrollPointer) {
        // 文件过期判断：首先是进入回收站状态，其次查询最后一次更新时间往后推7天就是要删除的
        QueryWrapper<UserFile> queryWrapper = Wrappers.query();
        queryWrapper.eq("del_flag", DelFlagEnum.YES.getCode());
        queryWrapper.le("update_time", getDateBeforeDays(7));
        queryWrapper.ge("file_id", scrollPointer);
        queryWrapper.last(" limit " + BATCH_SIZE);
        return userFileService.list(queryWrapper);
    }

    /**
     * 获取指定天数前的日期
     */
    private Date getDateBeforeDays(int days) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, -days);
        return calendar.getTime();
    }
}
